package ml2;

import java.util.Date;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public  class AbstractDeflector implements Deflector {

	protected StarBag _starBag;
	protected final double _startX;
	protected final double _startY;

	protected final double _sizeX;
	protected final double _sizeY;
	protected final int _nx;
	protected final int _ny;
	protected double[][] _magnificationMap;
	protected double[][] _shootingMap;
	protected final double _pixSize;
	protected long _lostFlux;
	protected long _totalFlux;
	protected double _currentX;
	protected double _currentY;
	protected long _initialTime;
	protected double microStep = DeflectionContext.pixSize/DeflectionContext.nRays;
	protected long _finalTime;
	private static String NEW_LINE = System.getProperty("line.separator");
	protected static Logger _log = Logger.getLogger(RandomDeflector.class);
	static{
		BasicConfigurator.configure();
	}

	protected AbstractDeflector(double[][] magnificationMap, double[][] shootingMap, StarBag starBag, 
			double startX, int nx,
			double startY, int ny,
			double sizeX, double sizeY,
			double pixelSize){
		_magnificationMap = magnificationMap;
		_shootingMap = shootingMap;
		_starBag = starBag;
		_startX = startX;
		_nx = nx;
		_ny = ny;
		_startY = startY;
		_pixSize = pixelSize;
		_totalFlux = 0;
		_lostFlux = 0;
		_sizeX = sizeX;
		_sizeY = sizeY;
		_currentX=0;
		_currentY=0;
	}

	protected double [] getDeflected(double xRay, double yRay) {
		double [] result = new double[]{xRay, yRay};
	
		//First the stars contribution.
		for (int i =0;i<_starBag.size();i++){
			double dx = xRay -_starBag.getX(i);
			double dy = yRay -_starBag.getY(i);
	
			double sep = dx*dx + dy*dy;
			result[0] -= dx/sep;
			result[1] -= dy/sep;
		}
	
		//The distributed mass and the shear
		result[0] -= (DeflectionContext.sigmaMatter + DeflectionContext.shear) * xRay;
		result[1] -= (DeflectionContext.sigmaMatter - DeflectionContext.shear) * yRay;
	
		return result;
	}
	@Override
	public long totalFlux(){
		return _totalFlux;
	}

	@Override
	public long lostFlux(){
		return _lostFlux;
	}

	@Override
	public double getProgress(){
		return 0;
	}
	@Override
	public double getElapsedTime(){
		return (double)(System.currentTimeMillis() - _initialTime)/1000;
	}
	@Override
	public double getUsedTime(){
		return (double)(_finalTime - _initialTime)/1000;
	}



	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		String threadName = Thread.currentThread().getName();
		double elapsed = getElapsedTime();
		double progress = getProgress();
		double remaining = elapsed*(1.0-progress)/progress;
		Date finishDate = new Date(System.currentTimeMillis() + (int)remaining*1000);
		result.append("============================================" + NEW_LINE);
		result.append("Thread:" + threadName + NEW_LINE);
	
		result.append("Start X: " + _startX+ NEW_LINE);
		result.append("Start Y: " + _startY+ NEW_LINE);
		result.append("Pixel size : " + _pixSize+ NEW_LINE);
		result.append("Progress " + getProgress()+ NEW_LINE);
		result.append("Elapsed time:" + Utils.toHHmmss(elapsed) + NEW_LINE);
		result.append("Remaining time:" + Utils.toHHmmss(remaining) + NEW_LINE);
		result.append("Finishing around:" + finishDate.toString() + NEW_LINE);
		result.append("============================================" + NEW_LINE);
	
		return result.toString();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}

}
